package com.linkq.ipinyin.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.linkq.core.base.BaseService;
import com.linkq.ipinyin.dao.StudyPlanDao;
import com.linkq.ipinyin.mapper.*;
import com.linkq.ipinyin.model.*;
import com.linkq.ipinyin.model.vo.AnswerVo;
import com.linkq.ipinyin.model.vo.CharacterAnswerVo;
import com.linkq.ipinyin.model.vo.StudyExamVo;
import com.linkq.ipinyin.utils.DateUtils;
import com.linkq.ipinyin.vo.ResultInfo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @FileName BcStudyPlanService
 * @Description
 * @Author wangpeng
 * @date 2025-01-01
 **/

@Service
@Transactional
public class StudyPlanService extends BaseService<StudyPlanDao, StudyPlan> {
    @Autowired
    private StudyPlanMapper studyPlanMapper;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private ExecutionPlanMapper executionPlanMapper;

    @Autowired
    private PopQuizMapper popQuizMapper;

    @Autowired
    private TextContentMapper textContentMapper;

    @Autowired
    private ExecutionContentMapper executionContentMapper;

    @Autowired
    private ExecutionContentService executionContentService;

    @Autowired
    private CnCharacterMapper characterMapper;

    /**
     * 创建学习计划
     * @param studyPlan
     * @return
     */
    public ResultInfo add(StudyPlan studyPlan) {
        studyPlan.setIsCreateExecution(0);
        studyPlan.setIsComplete(0);
        int row = studyPlanMapper.insert(studyPlan);
        if (row > 0) {
            return ResultInfo.success(row);
        }
        return ResultInfo.error("创建学习计划失败", row);
    }

    /**
     * 查询学习计划
     * @param studyPlan
     * @return
     */
    public ResultInfo getStudyInfo(StudyPlan studyPlan) {
        List<StudyPlan> studyPlans = studyPlanMapper.selectList(
                Wrappers.<StudyPlan>lambdaQuery()
                        .eq(!Objects.isNull(studyPlan.getCreateUser()), StudyPlan::getCreateUser, studyPlan.getCreateUser())
                        .like(StringUtils.isNotBlank(studyPlan.getPlanName()), StudyPlan::getPlanName, studyPlan.getPlanName())
                        .eq(!Objects.isNull(studyPlan.getId()), StudyPlan::getId, studyPlan.getId())
                        .ge(!Objects.isNull(studyPlan.getStartTime()), StudyPlan::getStartTime, studyPlan.getStartTime())
                        .le(!Objects.isNull(studyPlan.getEndTime()), StudyPlan::getEndTime, studyPlan.getEndTime())
                        .orderByDesc(StudyPlan::getStartTime)
        );
        List<StudyPlan> completeList = studyPlans.stream().filter(x -> null != x.getIsComplete() && x.getIsComplete() == 1).collect(Collectors.toList());
        List<StudyPlan> unReadyList = studyPlans.stream().filter(x -> x.getStartTime().after(new Date())).collect(Collectors.toList());
        List<StudyPlan> executingList = studyPlans.stream().filter(x -> x.getStartTime().before(new Date()) && x.getIsComplete() == 0).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(completeList)) {
            completeList = completeList.stream().sorted((o1, o2) -> o1.getStartTime().before(o2.getStartTime()) ? 1 : -1).collect(Collectors.toList());
        }
        if (CollectionUtils.isNotEmpty(unReadyList)) {
            unReadyList = unReadyList.stream().sorted((o1, o2) -> o1.getStartTime().before(o2.getStartTime()) ? -1 : 1).collect(Collectors.toList());
        }
        if (CollectionUtils.isNotEmpty(executingList)) {
            executingList = executingList.stream().sorted((o1, o2) -> o1.getStartTime().before(o2.getStartTime()) ? 1 : -1).collect(Collectors.toList());
        }
        JSONObject result = new JSONObject();
        result.put("completeList", completeList);
        result.put("unReadyList", unReadyList);
        result.put("executingList", executingList);
        return ResultInfo.success(result);
    }

    public ResultInfo getStudyExecution(StudyPlan studyPlan) {
        StudyPlan original = studyPlanMapper.selectById(studyPlan.getId());
        List<ExecutionPlan> executionPlans = executionPlanMapper.selectList(
                Wrappers.<ExecutionPlan>lambdaQuery()
                        .eq(ExecutionPlan::getPlanId, studyPlan.getId())
        );
        executionPlans.forEach(x -> {
            List<ExecutionContent> executionContentList = executionContentMapper.selectList(
                    Wrappers.<ExecutionContent>lambdaQuery()
                            .eq(ExecutionContent::getExecutionPlanId, x.getId())
            );
            if (CollectionUtils.isNotEmpty(executionContentList)) {
                List<CnCharacter> characterList = characterMapper.selectList(
                        Wrappers.<CnCharacter>lambdaQuery()
                                .in(CnCharacter::getId, executionContentList.stream().map(ExecutionContent::getCharacterId).collect(Collectors.toList()))
                );
                characterList.forEach(ch -> {
                    List<ExecutionContent> filterCharacterList = executionContentList.stream().filter(e -> e.getCharacterId() == ch.getId()).collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(filterCharacterList)) {
                        ch.setIsCorrect(filterCharacterList.get(0).getIsCorrect());
                    }
                });
                x.setCharacterList(characterList);
            }
        });
        original.setExecutionPlanList(executionPlans);
        return ResultInfo.success(original);
    }

    /**
     * 执行学习计划
     * @param studyExamVo
     * @return
     */
    public ResultInfo executePlan(StudyExamVo studyExamVo) {
        ExecutionPlan originPlan = executionPlanMapper.selectById(studyExamVo.getExecutionPlan().getId());
        List<ExecutionContent> executionContentList = executionContentMapper.selectList(
                Wrappers.<ExecutionContent>lambdaQuery()
                        .eq(ExecutionContent::getExecutionPlanId, originPlan.getId())
        );
        if (CollectionUtils.isEmpty(executionContentList)) {
            return ResultInfo.error("测验题目不存在", -1);
        }
        // 处理课后测验题目
        List<Integer> correctIds = studyExamVo.getCharacterAnswers().stream().filter(x -> x.getIsCorrect() == 1).map(CharacterAnswerVo::getCharacterId).collect(Collectors.toList());
        List<Integer> wrongIds = studyExamVo.getCharacterAnswers().stream().filter(x -> x.getIsCorrect() == 2).map(CharacterAnswerVo::getCharacterId).collect(Collectors.toList());
        List<Integer> undoIds = executionContentList.stream().filter(x -> !correctIds.contains(x.getCharacterId()) && !wrongIds.contains(x.getCharacterId())).map(ExecutionContent::getCharacterId).collect(Collectors.toList());

        // 更新执行计划状态
        ExecutionPlan executionPlan = studyExamVo.getExecutionPlan();
        executionPlan.setExecuteEndTime(new Date());
        executionPlan.setStatus(2);
        executionPlanMapper.updateById(executionPlan);
        // 更新学习计划
        List<ExecutionPlan> allPlans = executionPlanMapper.selectList(
                Wrappers.<ExecutionPlan>lambdaQuery()
                        .eq(ExecutionPlan::getPlanId, executionPlan.getPlanId())
        );
        long unFinished = allPlans.stream().filter(plan -> Objects.isNull(plan.getExecuteEndTime())).count();
        if (unFinished == 0) {
            StudyPlan studyPlan = studyPlanMapper.selectById(executionPlan.getPlanId());
            studyPlan.setIsComplete(1);
            studyPlanMapper.updateById(studyPlan);
        }
        // 更新答题
        UpdateWrapper<ExecutionContent> correctWrapper = new UpdateWrapper<>();
        if (CollectionUtils.isNotEmpty(correctIds)) {
            correctWrapper.lambda().in(ExecutionContent::getCharacterId, correctIds)
                    .eq(ExecutionContent::getExecutionPlanId, originPlan.getId())
                    .set(ExecutionContent::getIsCorrect, 1);
            executionContentMapper.update(null, correctWrapper);
        }
        if (CollectionUtils.isNotEmpty(wrongIds)) {
            UpdateWrapper<ExecutionContent> wrongWrapper = new UpdateWrapper<>();
            wrongWrapper.lambda().in(ExecutionContent::getCharacterId, wrongIds)
                    .eq(ExecutionContent::getExecutionPlanId, originPlan.getId())
                    .set(ExecutionContent::getIsCorrect, 2);
            executionContentMapper.update(null, wrongWrapper);
        }
        if (CollectionUtils.isNotEmpty(undoIds)) {
            UpdateWrapper<ExecutionContent> undoWrapper = new UpdateWrapper<>();
            undoWrapper.lambda().in(ExecutionContent::getCharacterId, undoIds)
                    .eq(ExecutionContent::getExecutionPlanId, originPlan.getId())
                    .set(ExecutionContent::getIsCorrect, 3);
            executionContentMapper.update(null, undoWrapper);
        }
        // begin更新下一次学习计划
        ExecutionPlan nextPlan = executionPlanMapper.selectOne(
                Wrappers.<ExecutionPlan>lambdaQuery()
                        .eq(ExecutionPlan::getPlanId, originPlan.getPlanId())
                        .eq(ExecutionPlan::getSort, originPlan.getSort() + 1)
        );
        if (!Objects.isNull(nextPlan)) {
            // 更新错题
            if (CollectionUtils.isNotEmpty(wrongIds)) {
                wrongIds.forEach(x -> {
                    ExecutionContent executionContent = new ExecutionContent();
                    executionContent.setExecutionPlanId(nextPlan.getId());
                    executionContent.setQuestionType(2);
                    executionContent.setCharacterId(x);
                    executionContent.setIsCorrect(3);
                    executionContentMapper.insert(executionContent);
                });
            }
            // 更新下一次学习计划的修正开始、结束时间
            if (!DateUtils.isSameDay(originPlan.getExecuteStartTime(), originPlan.getPlanStartTime())) {
                Date newStartTime = DateUtils.dateCaculate(originPlan.getExecuteStartTime(), 1, Calendar.DAY_OF_MONTH);
                Date newEndTime = DateUtils.dateCaculate(newStartTime, 1, Calendar.DAY_OF_MONTH);
                nextPlan.setCorrectStartTime(newStartTime);
                nextPlan.setCorrectEndTime(newEndTime);
                executionPlanMapper.updateById(nextPlan);
            }
        }
        // end 更新下一次学习计划
        return ResultInfo.success();
    }

    private List<Integer> getScore(Integer executePlanId, List<AnswerVo> answers) {
        List<Integer> wrongQuestionIds = new ArrayList<>();
        for(AnswerVo answer : answers) {
            Question question = questionMapper.selectById(answer.getQuestionId());
            List<PopQuiz> popQuizs = popQuizMapper.selectList(
                    Wrappers.<PopQuiz>lambdaQuery()
                            .eq(PopQuiz::getExecutionId, executePlanId)
                            .eq(PopQuiz::getQuestionId, answer.getQuestionId())
            );
            if (CollectionUtils.isEmpty(popQuizs)) {
                continue;
            }
            PopQuiz popQuiz = popQuizs.get(0);
            Integer questionType = question.getQuestionType();
            if (questionType == 1) {// 单选题
                if (StringUtils.equals(answer.getAnswer(), question.getCorrect())) {
                    popQuiz.setIsCorrect(1);
                } else {
                    popQuiz.setIsCorrect(2);
                    wrongQuestionIds.add(answer.getQuestionId());
                }
            } else if (questionType == 4){ // 填空题， 多个空以**分隔
                List<String> answerList = Arrays.asList(answer.getAnswer().split("\\*\\*"));
                TextContent textContent = textContentMapper.selectById(question.getInfoTextContentId());
                JSONObject content = JSON.parseObject(textContent.getContent());
                JSONArray questionItemObjects = JSONArray.parseArray(content.getString("questionItemObjects"));
                questionItemObjects.sort(Comparator.comparingInt(o -> JSONObject.parseObject(o.toString()).getInteger("prefix")));
                boolean doRight = true;
                int[] blanks = new int[questionItemObjects.size()];
                for(int i = 0; i < questionItemObjects.size(); i++) {
                    JSONObject item = JSON.parseObject(questionItemObjects.getString(i));
                    if (StringUtils.equals(item.getString("content"), answerList.get(i))) {
                        blanks[i] = 1;
                    } else {
                        doRight = false;
                        wrongQuestionIds.add(answer.getQuestionId());
                    }
                }
                popQuiz.setIsCorrect(doRight ? 1 : 2);
            }
            popQuizMapper.updateById(popQuiz);
        }
        return wrongQuestionIds;
    }

    public ResultInfo delete(StudyPlan studyPlan) {
        StudyPlan origin = studyPlanMapper.selectById(studyPlan);
        if (!Objects.isNull(origin)) {
            if (studyPlanMapper.deleteById(origin.getId()) > 0) {
                return ResultInfo.success(1, "删除学习计划成功");
            }
        }
        return ResultInfo.error("删除学习计划失败", -1);
    }
}
